{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7fc03329-593b-4661-b404-1ccc3d863931",
   "metadata": {},
   "source": [
    "# Plot Tutorial"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c8263e7-f98c-4fda-851c-5130700416b2",
   "metadata": {},
   "source": [
    "This notebook covers the plot functions implemented in NetworKit. The plots help to evaluate and visualize certain properties of a graph.  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bbfa3f72-f280-40e9-922f-bdb1a377018b",
   "metadata": {},
   "source": [
    "Note: The `matplotlib` library, as well as the `seaborn` library needs to be installed on your device. For example use `pip install matplotlib` to obtain it."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5696bf1d-e957-4ef1-809d-e24ad968a1ae",
   "metadata": {},
   "source": [
    "The first step is to import NetworKit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c3ce52b7-8bcf-4b13-b534-ab985bcc1cc0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import networkit as nk"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8aa7424-ec87-4000-a534-911391622e84",
   "metadata": {},
   "source": [
    "### DegreeDistribution"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dca097a2-98d5-4c2d-a1af-b8026c3a4216",
   "metadata": {},
   "source": [
    "The `degreeDistribution` of a graph describes the degree (incoming and outgoing edges) that each node has. `Networkit.plot.degreeDistribution` plots how many nodes of each degree exist within a graph."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e70c3e8-22f4-489e-a216-23f73b8dabf6",
   "metadata": {},
   "source": [
    "We start by creating a graph `G`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f29ff769-4f61-4410-994e-7a358c334b02",
   "metadata": {},
   "outputs": [],
   "source": [
    "G=nk.Graph(7)\n",
    "G.addEdge(0,1)\n",
    "G.addEdge(0,2)\n",
    "G.addEdge(1,2)\n",
    "G.addEdge(2,3)\n",
    "G.addEdge(2,4) \n",
    "G.addEdge(3,5)\n",
    "G.addEdge(5,6) "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "25dc080c-acb9-4f25-88ee-ed1d42e50f87",
   "metadata": {
    "tags": []
   },
   "source": [
    "Plotting the `degreeDistribution` of a graph `G` can be done the following way:  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a60591b2-ba51-430c-8803-d477b98a0b05",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "nk.plot.degreeDistribution(G)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d421a240-5862-44eb-a045-223bc1636f91",
   "metadata": {},
   "source": [
    "### ConnectedComponentsSizes"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4ec90373-5827-4dd9-9d5f-443ae4967675",
   "metadata": {},
   "source": [
    "The `connectedComponentsSizes` describe how many nodes of the graph the individual connected components contain. `Networkit.plot.connectedComponentsSizes` plots for each indivual component how many nodes of the graph it contains. By default it shows the size relative (as percentages) to the entire population, if `relativeSizes` is set to `False`, it shows the absolute number of nodes in each component."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0f3378e-864d-4eac-ac3a-45de4887e497",
   "metadata": {},
   "source": [
    "Note: See [networkit.components.ConnectedComponents](https://networkit.github.io/dev-docs/python_api/components.html?highlight=connectedcomponents#networkit.components.ConnectedComponents) for a description of the algorithm."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1045ad32-1580-4ff6-a422-a9d7e870bc21",
   "metadata": {},
   "source": [
    "For the next example we create a new graph `G2` with 3 components: the first component contains the nodes 0-3, the second contains the nodes 4 and 5, and the third contains only node 6 (component of size 1)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9ccbf5e0-8ef5-45cb-b66a-4214651334d1",
   "metadata": {},
   "outputs": [],
   "source": [
    "G2=nk.Graph(7)\n",
    "G2.addEdge(0,1) \n",
    "G2.addEdge(1,2)\n",
    "G2.addEdge(2,3)\n",
    "G2.addEdge(4,5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e6abfb6-1482-4cbe-99e9-a69369db4020",
   "metadata": {},
   "source": [
    "Plotting the `connectedComponentsSizes` of a graph `G` can be done the following way:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8753a661-d298-4dd2-a454-84fe7cf412bb",
   "metadata": {},
   "outputs": [],
   "source": [
    "nk.plot.connectedComponentsSizes(G2, relativeSizes=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d17750f0-4a08-43bd-b1fc-2eaed1d8ef59",
   "metadata": {},
   "source": [
    "### NodeAttributes"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57046d74-32f7-4298-b1cb-ad304954a052",
   "metadata": {},
   "source": [
    "The `nodeAttributes` are useful in order to efficiently incorporate additional information in the graph data structure."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c1d2ca5-71cb-4b37-91a1-5fa34f4d9ede",
   "metadata": {},
   "source": [
    "Note: See [networkit.GraphTutorial](https://networkit.github.io/dev-docs/notebooks/GraphNotebook.html) in section `NodeAttributes` for a detailed description."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f0fb9b5-15b0-4d02-88bb-57666359757c",
   "metadata": {},
   "source": [
    "For this example we create a new graph `G_attr` which contains additional graph attributes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5e625b9e-d176-45e6-8949-dda910fd8c54",
   "metadata": {},
   "outputs": [],
   "source": [
    "G_attr=nk.Graph(4)\n",
    "G_attr.addEdge(0,1) \n",
    "G_attr.addEdge(1,2) \n",
    "G_attr.addEdge(2,3)\n",
    "#attaching the attributes to the graph\n",
    "attrFloat = G_attr.attachNodeAttribute(\"myFloat\", float)\n",
    "attrStr = G_attr.attachNodeAttribute(\"myStr\", str)\n",
    "#setting attribute values\n",
    "attrFloat[0] = 0.5\n",
    "attrFloat[1] = 1.5\n",
    "attrStr[1] = \"tutorial\"\n",
    "attrStr[2] = \"again\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b3fab65-4869-4947-91ac-6151aae40065",
   "metadata": {},
   "source": [
    "Note: The `nk.plot.nodeAttributes` can only be called with either one `nodeAttribute` or a `tuple` of exactly two `nodeAttributes`. \n",
    "\n",
    "- If called with a single `nodeAttribute`, it plots how frequent each value of the `nodeAttribute` is present in the graph.\n",
    "\n",
    "- If called with two `nodeAttributes`, it plots the 2-Dimensional distribution of the nodes according to the given `nodeAttributes`\n",
    "\n",
    "Plotting the `nodeAttributes` of a graph `G` can be done the following way:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "512ed50a-0ac7-4425-820a-8558a6fb86e7",
   "metadata": {},
   "outputs": [],
   "source": [
    "#example with a single attribute\n",
    "nk.plot.nodeAttributes(G_attr, attrFloat)\n",
    "\n",
    "#example with two attributes\n",
    "nk.plot.nodeAttributes(G_attr, (attrFloat, attrStr))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3f42daa2-cfe3-4ff0-9e3b-b73a0aa208e3",
   "metadata": {},
   "source": [
    "### ClusteringPerDegree"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1dcb32c5-a706-4996-91e9-cc1bc1ed16cd",
   "metadata": {},
   "source": [
    "`ClusteringPerDegree` can be used as `centrality` measure of the graph. `Networkit.plot.ClusteringPerDegree` plots for each degree (obtained by [DegreeCentrality](https://networkit.github.io/dev-docs/python_api/centrality.html?highlight=degreecentr#networkit.centrality.DegreeCentrality)) the so called [Clustering Coefficient](https://en.wikipedia.org/wiki/Clustering_coefficient) `(cc)` that measures how tight adjacent nodes are clustered together."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8eaae1c-3c28-4efc-99d9-3792d75c9430",
   "metadata": {},
   "source": [
    "For this example we read a medium sized graph given by the `networkit.input` graphs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fba809e7-26a4-4705-80c7-e7cfddcadf94",
   "metadata": {},
   "outputs": [],
   "source": [
    "# read a graph\n",
    "G_jazz = nk.readGraph(\"../input/jazz.graph\", nk.Format.METIS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d19b1044-5bf3-42b3-9457-eb03d01a2304",
   "metadata": {},
   "source": [
    "Note: The `pandas` library, as well as the `seaborn` library needs to be installed on your device."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "050d5d61-fbe1-470c-86e0-3cac8ed4500e",
   "metadata": {},
   "source": [
    "Plotting the `ClusteringPerDegree` of a graph `G` can be done the following way:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8c017a8c-3499-4c6a-a06b-d11bbce63144",
   "metadata": {},
   "outputs": [],
   "source": [
    "nk.plot.clusteringPerDegree(G_jazz)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d841ec12-d9f7-46f0-9ebf-2ebb9f65dd87",
   "metadata": {},
   "source": [
    "### CoreDecomposition"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "792aa51b-f0bf-4763-9dd0-cfe0b2431abb",
   "metadata": {},
   "source": [
    "The `CoreDecomposition` algorithm computes the k-core decomposition of a graph, which is the largest induced subgraph, only consisting of nodes, whose degree is greater than or equal to `k`. `Networkit.plot.coreDecompositionSequence` plots the size (number of nodes) of each k-induced subgraph."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0411819c-0975-4aa2-89dd-2f4008f0e820",
   "metadata": {},
   "source": [
    "See [networkit.centrality.coreDecomposition](https://networkit.github.io/dev-docs/python_api/centrality.html?highlight=coredecomp#networkit.centrality.CoreDecomposition) for a description of the algorithm."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3773230f-315d-4fdc-9e64-2161190b8c01",
   "metadata": {},
   "source": [
    "For the next example we create a new graph `G3`, whose k2-shell has size 4 (nodes: 1,3,4,5) and whose k1-shell has size 2 (nodes 0 and 2). "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6dd76346-aecb-42a5-af66-259b66c5ce14",
   "metadata": {},
   "outputs": [],
   "source": [
    "G3=nk.Graph(6)\n",
    "G3.addEdge(0,3) # G3:  0\n",
    "G3.addEdge(1,3) #      |\n",
    "G3.addEdge(2,3) #  1 - 3 - 2\n",
    "G3.addEdge(1,4) #  | X |\n",
    "G3.addEdge(1,5) #  4 - 5  \n",
    "G3.addEdge(3,4) \n",
    "G3.addEdge(4,5)\n",
    "G3.addEdge(3,5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "347f9887-90f0-41e1-bdce-d3a5eff21546",
   "metadata": {},
   "source": [
    "Plotting the `coreDecompositionSequence` of a graph `G` can be done the following way:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "94466739-16fd-4e16-8a55-f71fd05039da",
   "metadata": {},
   "outputs": [],
   "source": [
    "nk.plot.coreDecompositionSequence(G3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5735c0b-3fdb-47f3-8c5f-5000dcf66952",
   "metadata": {
    "tags": []
   },
   "source": [
    "### HopPlot"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c48a2166-91ba-4c3e-9523-72c099d41c35",
   "metadata": {},
   "source": [
    "The `hopPlot` is the set of pairs `(d, g(d))` for each natural number `d`, where `g(d)` is the fraction of connected node pairs whose shortest connecting path has length at most `d`. The `networkit.plot.hopPlot` plots the percentage of connected node pairs, that have a connecting path of length at most `d`. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c521d40a-b5cc-4bf4-aa23-48ad05a81135",
   "metadata": {},
   "source": [
    "Note: The algorithm is approximative. See [networkit.distance.hopPlotApproximation](https://networkit.github.io/dev-docs/python_api/distance.html?highlight=hopplotapp#networkit.distance.HopPlotApproximation) for a detailed description of the algorithm."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a336218e-c140-4173-b9dc-3fc6a3752693",
   "metadata": {},
   "source": [
    "For this example we read a medium sized graph given by the `networkit.input` graphs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6f2674c8-de79-43cb-893a-61b8d50dbddd",
   "metadata": {},
   "outputs": [],
   "source": [
    "#larger example\n",
    "G_big = nk.readGraph(\"../input/power.graph\", nk.Format.METIS)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf4e7edb-1c39-4266-8114-6d9bcdec9d96",
   "metadata": {},
   "source": [
    "Plotting the `hopPlot` of a graph `G` can be done the following way:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7919e192-6353-45eb-877f-94fae5494173",
   "metadata": {},
   "outputs": [],
   "source": [
    "nk.plot.hopPlot(G_big)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
